Conditions | 2 |
Paths | > 20000 |
Total Lines | 525 |
Code Lines | 363 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | // ---------------------------------------------------------------------------- |
||
28 | $.fn.markItUp = function(settings, extraSettings) { |
||
29 | var options, ctrlKey, shiftKey, altKey; |
||
30 | ctrlKey = shiftKey = altKey = false; |
||
31 | |||
32 | options = { id: '', |
||
33 | nameSpace: '', |
||
34 | root: '', |
||
35 | previewInWindow: '', // 'width=800, height=600, resizable=yes, scrollbars=yes' |
||
36 | previewAutoRefresh: true, |
||
37 | previewPosition: 'after', |
||
38 | previewTemplatePath: '~/templates/preview.html', |
||
39 | previewParserPath: '', |
||
40 | previewParserVar: 'data', |
||
41 | resizeHandle: true, |
||
42 | beforeInsert: '', |
||
43 | afterInsert: '', |
||
44 | onEnter: {}, |
||
45 | onShiftEnter: {}, |
||
46 | onCtrlEnter: {}, |
||
47 | onTab: {}, |
||
48 | markupSet: [ { /* set */ } ] |
||
49 | }; |
||
50 | $.extend(options, settings, extraSettings); |
||
51 | |||
52 | // compute markItUp! path |
||
53 | if (!options.root) { |
||
54 | $('script').each(function(a, tag) { |
||
55 | miuScript = $(tag).get(0).src.match(/(.*)jquery\.markitup(\.pack)?\.js/); |
||
|
|||
56 | if (miuScript !== null) { |
||
57 | options.root = miuScript[1]; |
||
58 | } |
||
59 | }); |
||
60 | } |
||
61 | |||
62 | return this.each(function() { |
||
63 | var $$, textarea, levels, scrollPosition, caretPosition, caretOffset, |
||
64 | clicked, hash, header, footer, previewWindow, template, iFrame, abort; |
||
65 | $$ = $(this); |
||
66 | textarea = this; |
||
67 | levels = []; |
||
68 | abort = false; |
||
69 | scrollPosition = caretPosition = 0; |
||
70 | caretOffset = -1; |
||
71 | |||
72 | options.previewParserPath = localize(options.previewParserPath); |
||
73 | options.previewTemplatePath = localize(options.previewTemplatePath); |
||
74 | |||
75 | // apply the computed path to ~/ |
||
76 | function localize(data, inText) { |
||
77 | if (inText) { |
||
78 | return data.replace(/("|')~\//g, "$1"+options.root); |
||
79 | } |
||
80 | return data.replace(/^~\//, options.root); |
||
81 | } |
||
82 | |||
83 | // init and build editor |
||
84 | function init() { |
||
85 | id = ''; nameSpace = ''; |
||
86 | if (options.id) { |
||
87 | id = 'id="'+options.id+'"'; |
||
88 | } else if ($$.attr("id")) { |
||
89 | id = 'id="markItUp'+($$.attr("id").substr(0, 1).toUpperCase())+($$.attr("id").substr(1))+'"'; |
||
90 | |||
91 | } |
||
92 | if (options.nameSpace) { |
||
93 | nameSpace = 'class="'+options.nameSpace+'"'; |
||
94 | } |
||
95 | $$.wrap('<div '+nameSpace+'></div>'); |
||
96 | $$.wrap('<div '+id+' class="markItUp"></div>'); |
||
97 | $$.wrap('<div class="markItUpContainer"></div>'); |
||
98 | $$.addClass("markItUpEditor"); |
||
99 | |||
100 | // add the header before the textarea |
||
101 | header = $('<div class="markItUpHeader"></div>').insertBefore($$); |
||
102 | $(dropMenus(options.markupSet)).appendTo(header); |
||
103 | |||
104 | // add the footer after the textarea |
||
105 | footer = $('<div class="markItUpFooter"></div>').insertAfter($$); |
||
106 | |||
107 | // add the resize handle after textarea |
||
108 | if (options.resizeHandle === true) { |
||
109 | resizeHandle = $('<div class="markItUpResizeHandle"></div>') |
||
110 | .insertAfter($$) |
||
111 | .bind("mousedown", function(e) { |
||
112 | var h = $$.height(), y = e.clientY, mouseMove, mouseUp; |
||
113 | mouseMove = function(e) { |
||
114 | $$.css("height", Math.max(20, e.clientY+h-y)+"px"); |
||
115 | return false; |
||
116 | }; |
||
117 | mouseUp = function(e) { |
||
118 | $("html").unbind("mousemove", mouseMove).unbind("mouseup", mouseUp); |
||
119 | return false; |
||
120 | }; |
||
121 | $("html").bind("mousemove", mouseMove).bind("mouseup", mouseUp); |
||
122 | }); |
||
123 | footer.append(resizeHandle); |
||
124 | } |
||
125 | |||
126 | // listen key events |
||
127 | $$.keydown(keyPressed).keyup(keyPressed); |
||
128 | |||
129 | // bind an event to catch external calls |
||
130 | $$.bind("insertion", function(e, settings) { |
||
131 | if (settings.target !== false) { |
||
132 | get(); |
||
133 | } |
||
134 | if (textarea === $.markItUp.focused) { |
||
135 | markup(settings); |
||
136 | } |
||
137 | }); |
||
138 | |||
139 | // remember the last focus |
||
140 | $$.focus(function() { |
||
141 | $.markItUp.focused = this; |
||
142 | }); |
||
143 | } |
||
144 | |||
145 | // recursively build header with dropMenus from markupset |
||
146 | function dropMenus(markupSet) { |
||
147 | var ul = $('<ul></ul>'), i = 0; |
||
148 | $('li:hover > ul', ul).css('display', 'block'); |
||
149 | $.each(markupSet, function() { |
||
150 | var button = this, t = '', title, li, j; |
||
151 | title = (button.key) ? (button.name||'')+' [Ctrl+'+button.key+']' : (button.name||''); |
||
152 | key = (button.key) ? 'accesskey="'+button.key+'"' : ''; |
||
153 | if (button.separator) { |
||
154 | li = $('<li class="markItUpSeparator">'+(button.separator||'')+'</li>').appendTo(ul); |
||
155 | } else { |
||
156 | i++; |
||
157 | for (j = levels.length -1; j >= 0; j--) { |
||
158 | t += levels[j]+"-"; |
||
159 | } |
||
160 | li = $('<li class="markItUpButton markItUpButton'+t+(i)+' '+(button.className||'')+'"><a href="" '+key+' title="'+title+'">'+(button.name||'')+'</a></li>') |
||
161 | .bind("contextmenu", function() { // prevent contextmenu on mac and allow ctrl+click |
||
162 | return false; |
||
163 | }).click(function() { |
||
164 | return false; |
||
165 | }).bind("focusin", function(){ |
||
166 | $$.focus(); |
||
167 | }).mousedown(function() { |
||
168 | if (button.call) { |
||
169 | eval(button.call)(); |
||
170 | } |
||
171 | setTimeout(function() { markup(button) },1); |
||
172 | return false; |
||
173 | }).hover(function() { |
||
174 | $('> ul', this).show(); |
||
175 | $(document).one('click', function() { // close dropmenu if click outside |
||
176 | $('ul ul', header).hide(); |
||
177 | } |
||
178 | ); |
||
179 | }, function() { |
||
180 | $('> ul', this).hide(); |
||
181 | } |
||
182 | ).appendTo(ul); |
||
183 | if (button.dropMenu) { |
||
184 | levels.push(i); |
||
185 | $(li).addClass('markItUpDropMenu').append(dropMenus(button.dropMenu)); |
||
186 | } |
||
187 | } |
||
188 | }); |
||
189 | levels.pop(); |
||
190 | return ul; |
||
191 | } |
||
192 | |||
193 | // markItUp! markups |
||
194 | function magicMarkups(string) { |
||
195 | if (string) { |
||
196 | string = string.toString(); |
||
197 | string = string.replace(/\(\!\(([\s\S]*?)\)\!\)/g, |
||
198 | function(x, a) { |
||
199 | var b = a.split('|!|'); |
||
200 | if (altKey === true) { |
||
201 | return (b[1] !== undefined) ? b[1] : b[0]; |
||
202 | } else { |
||
203 | return (b[1] === undefined) ? "" : b[0]; |
||
204 | } |
||
205 | } |
||
206 | ); |
||
207 | // [![prompt]!], [![prompt:!:value]!] |
||
208 | string = string.replace(/\[\!\[([\s\S]*?)\]\!\]/g, |
||
209 | function(x, a) { |
||
210 | var b = a.split(':!:'); |
||
211 | if (abort === true) { |
||
212 | return false; |
||
213 | } |
||
214 | value = prompt(b[0], (b[1]) ? b[1] : ''); |
||
215 | if (value === null) { |
||
216 | abort = true; |
||
217 | } |
||
218 | return value; |
||
219 | } |
||
220 | ); |
||
221 | return string; |
||
222 | } |
||
223 | return ""; |
||
224 | } |
||
225 | |||
226 | // prepare action |
||
227 | function prepare(action) { |
||
228 | if ($.isFunction(action)) { |
||
229 | action = action(hash); |
||
230 | } |
||
231 | return magicMarkups(action); |
||
232 | } |
||
233 | |||
234 | // build block to insert |
||
235 | function build(string) { |
||
236 | var openWith = prepare(clicked.openWith); |
||
237 | var placeHolder = prepare(clicked.placeHolder); |
||
238 | var replaceWith = prepare(clicked.replaceWith); |
||
239 | var closeWith = prepare(clicked.closeWith); |
||
240 | if (replaceWith !== "") { |
||
241 | block = openWith + replaceWith + closeWith; |
||
242 | } else if (selection === '' && placeHolder !== '') { |
||
243 | block = openWith + placeHolder + closeWith; |
||
244 | } else { |
||
245 | string = string || selection; |
||
246 | if (string.match(/ $/)) { |
||
247 | block = openWith + string.replace(/ $/, '') + closeWith + ' '; |
||
248 | } else { |
||
249 | block = openWith + string + closeWith; |
||
250 | } |
||
251 | } |
||
252 | return { block:block, |
||
253 | openWith:openWith, |
||
254 | replaceWith:replaceWith, |
||
255 | placeHolder:placeHolder, |
||
256 | closeWith:closeWith |
||
257 | }; |
||
258 | } |
||
259 | |||
260 | // define markup to insert |
||
261 | function markup(button) { |
||
262 | var len, j, n, i; |
||
263 | hash = clicked = button; |
||
264 | get(); |
||
265 | |||
266 | $.extend(hash, { line:"", |
||
267 | root:options.root, |
||
268 | textarea:textarea, |
||
269 | selection:(selection||''), |
||
270 | caretPosition:caretPosition, |
||
271 | ctrlKey:ctrlKey, |
||
272 | shiftKey:shiftKey, |
||
273 | altKey:altKey |
||
274 | } |
||
275 | ); |
||
276 | // callbacks before insertion |
||
277 | prepare(options.beforeInsert); |
||
278 | prepare(clicked.beforeInsert); |
||
279 | if (ctrlKey === true && shiftKey === true) { |
||
280 | prepare(clicked.beforeMultiInsert); |
||
281 | } |
||
282 | $.extend(hash, { line:1 }); |
||
283 | |||
284 | if (ctrlKey === true && shiftKey === true) { |
||
285 | lines = selection.split(/\r?\n/); |
||
286 | for (j = 0, n = lines.length, i = 0; i < n; i++) { |
||
287 | if ($.trim(lines[i]) !== '') { |
||
288 | $.extend(hash, { line:++j, selection:lines[i] } ); |
||
289 | lines[i] = build(lines[i]).block; |
||
290 | } else { |
||
291 | lines[i] = ""; |
||
292 | } |
||
293 | } |
||
294 | string = { block:lines.join('\n')}; |
||
295 | start = caretPosition; |
||
296 | len = string.block.length + ((false) ? n-1 : 0); |
||
297 | } else if (ctrlKey === true) { |
||
298 | string = build(selection); |
||
299 | start = caretPosition + string.openWith.length; |
||
300 | len = string.block.length - string.openWith.length - string.closeWith.length; |
||
301 | len = len - (string.block.match(/ $/) ? 1 : 0); |
||
302 | len -= fixIeBug(string.block); |
||
303 | } else if (shiftKey === true) { |
||
304 | string = build(selection); |
||
305 | start = caretPosition; |
||
306 | len = string.block.length; |
||
307 | len -= fixIeBug(string.block); |
||
308 | } else { |
||
309 | string = build(selection); |
||
310 | start = caretPosition + string.block.length ; |
||
311 | len = 0; |
||
312 | start -= fixIeBug(string.block); |
||
313 | } |
||
314 | if ((selection === '' && string.replaceWith === '')) { |
||
315 | caretOffset += fixOperaBug(string.block); |
||
316 | |||
317 | start = caretPosition + string.openWith.length; |
||
318 | len = string.block.length - string.openWith.length - string.closeWith.length; |
||
319 | |||
320 | caretOffset = $$.val().substring(caretPosition, $$.val().length).length; |
||
321 | caretOffset -= fixOperaBug($$.val().substring(0, caretPosition)); |
||
322 | } |
||
323 | $.extend(hash, { caretPosition:caretPosition, scrollPosition:scrollPosition } ); |
||
324 | |||
325 | if (string.block !== selection && abort === false) { |
||
326 | insert(string.block); |
||
327 | set(start, len); |
||
328 | } else { |
||
329 | caretOffset = -1; |
||
330 | } |
||
331 | get(); |
||
332 | |||
333 | $.extend(hash, { line:'', selection:selection }); |
||
334 | |||
335 | // callbacks after insertion |
||
336 | if (ctrlKey === true && shiftKey === true) { |
||
337 | prepare(clicked.afterMultiInsert); |
||
338 | } |
||
339 | prepare(clicked.afterInsert); |
||
340 | prepare(options.afterInsert); |
||
341 | |||
342 | // refresh preview if opened |
||
343 | if (previewWindow && options.previewAutoRefresh) { |
||
344 | refreshPreview(); |
||
345 | } |
||
346 | |||
347 | // reinit keyevent |
||
348 | shiftKey = altKey = ctrlKey = abort = false; |
||
349 | } |
||
350 | |||
351 | // Substract linefeed in Opera |
||
352 | function fixOperaBug(string) { |
||
353 | if (false) { |
||
354 | return string.length - string.replace(/\n*/g, '').length; |
||
355 | } |
||
356 | return 0; |
||
357 | } |
||
358 | // Substract linefeed in IE |
||
359 | function fixIeBug(string) { |
||
360 | if (false) { |
||
361 | return string.length - string.replace(/\r/g, '').length; |
||
362 | } |
||
363 | return 0; |
||
364 | } |
||
365 | |||
366 | // add markup |
||
367 | function insert(block) { |
||
368 | if (document.selection) { |
||
369 | var newSelection = document.selection.createRange(); |
||
370 | newSelection.text = block; |
||
371 | } else { |
||
372 | textarea.value = textarea.value.substring(0, caretPosition) + block + textarea.value.substring(caretPosition + selection.length, textarea.value.length); |
||
373 | } |
||
374 | } |
||
375 | |||
376 | // set a selection |
||
377 | function set(start, len) { |
||
378 | if (textarea.createTextRange){ |
||
379 | // quick fix to make it work on Opera 9.5 |
||
380 | if (len == 0) { |
||
381 | return false; |
||
382 | } |
||
383 | range = textarea.createTextRange(); |
||
384 | range.collapse(true); |
||
385 | range.moveStart('character', start); |
||
386 | range.moveEnd('character', len); |
||
387 | range.select(); |
||
388 | } else if (textarea.setSelectionRange ){ |
||
389 | textarea.setSelectionRange(start, start + len); |
||
390 | } |
||
391 | textarea.scrollTop = scrollPosition; |
||
392 | textarea.focus(); |
||
393 | } |
||
394 | |||
395 | // get the selection |
||
396 | function get() { |
||
397 | textarea.focus(); |
||
398 | |||
399 | scrollPosition = textarea.scrollTop; |
||
400 | if (document.selection) { |
||
401 | selection = document.selection; |
||
402 | if (false) { // ie |
||
403 | var range = selection.createRange(); |
||
404 | var stored_range = range.duplicate(); |
||
405 | stored_range.moveToElementText(textarea); |
||
406 | stored_range.setEndPoint('EndToEnd', range); |
||
407 | var s = stored_range.text.length - range.text.length; |
||
408 | |||
409 | caretPosition = s - (textarea.value.substr(0, s).length - textarea.value.substr(0, s).replace(/\r/g, '').length); |
||
410 | selection = range.text; |
||
411 | } else { // opera |
||
412 | caretPosition = textarea.selectionStart; |
||
413 | } |
||
414 | } else { // gecko & webkit |
||
415 | caretPosition = textarea.selectionStart; |
||
416 | selection = textarea.value.substring(caretPosition, textarea.selectionEnd); |
||
417 | } |
||
418 | return selection; |
||
419 | } |
||
420 | |||
421 | // open preview window |
||
422 | function preview() { |
||
423 | if (!previewWindow || previewWindow.closed) { |
||
424 | if (options.previewInWindow) { |
||
425 | previewWindow = window.open('', 'preview', options.previewInWindow); |
||
426 | $(window).unload(function() { |
||
427 | previewWindow.close(); |
||
428 | }); |
||
429 | } else { |
||
430 | iFrame = $('<iframe class="markItUpPreviewFrame"></iframe>'); |
||
431 | if (options.previewPosition == 'after') { |
||
432 | iFrame.insertAfter(footer); |
||
433 | } else { |
||
434 | iFrame.insertBefore(header); |
||
435 | } |
||
436 | previewWindow = iFrame[iFrame.length - 1].contentWindow || frame[iFrame.length - 1]; |
||
437 | } |
||
438 | } else if (altKey === true) { |
||
439 | if (iFrame) { |
||
440 | iFrame.remove(); |
||
441 | } else { |
||
442 | previewWindow.close(); |
||
443 | } |
||
444 | previewWindow = iFrame = false; |
||
445 | } |
||
446 | if (!options.previewAutoRefresh) { |
||
447 | refreshPreview(); |
||
448 | } |
||
449 | if (options.previewInWindow) { |
||
450 | previewWindow.focus(); |
||
451 | } |
||
452 | } |
||
453 | |||
454 | // refresh Preview window |
||
455 | function refreshPreview() { |
||
456 | renderPreview(); |
||
457 | } |
||
458 | |||
459 | function renderPreview() { |
||
460 | var phtml; |
||
461 | if (options.previewParserPath !== '') { |
||
462 | $.ajax({ |
||
463 | type: 'POST', |
||
464 | dataType: 'text', |
||
465 | global: false, |
||
466 | url: options.previewParserPath, |
||
467 | data: options.previewParserVar+'='+encodeURIComponent($$.val()), |
||
468 | success: function(data) { |
||
469 | writeInPreview( localize(data, 1) ); |
||
470 | } |
||
471 | }); |
||
472 | } else { |
||
473 | if (!template) { |
||
474 | $.ajax({ |
||
475 | url: options.previewTemplatePath, |
||
476 | dataType: 'text', |
||
477 | global: false, |
||
478 | success: function(data) { |
||
479 | writeInPreview( localize(data, 1).replace(/<!-- content -->/g, $$.val()) ); |
||
480 | } |
||
481 | }); |
||
482 | } |
||
483 | } |
||
484 | return false; |
||
485 | } |
||
486 | |||
487 | function writeInPreview(data) { |
||
488 | if (previewWindow.document) { |
||
489 | try { |
||
490 | sp = previewWindow.document.documentElement.scrollTop |
||
491 | } catch(e) { |
||
492 | sp = 0; |
||
493 | } |
||
494 | previewWindow.document.open(); |
||
495 | previewWindow.document.write(data); |
||
496 | previewWindow.document.close(); |
||
497 | previewWindow.document.documentElement.scrollTop = sp; |
||
498 | } |
||
499 | } |
||
500 | |||
501 | // set keys pressed |
||
502 | function keyPressed(e) { |
||
503 | shiftKey = e.shiftKey; |
||
504 | altKey = e.altKey; |
||
505 | ctrlKey = (!(e.altKey && e.ctrlKey)) ? e.ctrlKey : false; |
||
506 | |||
507 | if (e.type === 'keydown') { |
||
508 | if (ctrlKey === true) { |
||
509 | li = $("a[accesskey="+String.fromCharCode(e.keyCode)+"]", header).parent('li'); |
||
510 | if (li.length !== 0) { |
||
511 | ctrlKey = false; |
||
512 | setTimeout(function() { |
||
513 | li.triggerHandler('mousedown'); |
||
514 | },1); |
||
515 | return false; |
||
516 | } |
||
517 | } |
||
518 | if (e.keyCode === 13 || e.keyCode === 10) { // Enter key |
||
519 | if (ctrlKey === true) { // Enter + Ctrl |
||
520 | ctrlKey = false; |
||
521 | markup(options.onCtrlEnter); |
||
522 | return options.onCtrlEnter.keepDefault; |
||
523 | } else if (shiftKey === true) { // Enter + Shift |
||
524 | shiftKey = false; |
||
525 | markup(options.onShiftEnter); |
||
526 | return options.onShiftEnter.keepDefault; |
||
527 | } else { // only Enter |
||
528 | markup(options.onEnter); |
||
529 | return options.onEnter.keepDefault; |
||
530 | } |
||
531 | } |
||
532 | if (e.keyCode === 9) { // Tab key |
||
533 | if (shiftKey == true || ctrlKey == true || altKey == true) { |
||
534 | return false; |
||
535 | } |
||
536 | if (caretOffset !== -1) { |
||
537 | get(); |
||
538 | caretOffset = $$.val().length - caretOffset; |
||
539 | set(caretOffset, 0); |
||
540 | caretOffset = -1; |
||
541 | return false; |
||
542 | } else { |
||
543 | markup(options.onTab); |
||
544 | return options.onTab.keepDefault; |
||
545 | } |
||
546 | } |
||
547 | } |
||
548 | } |
||
549 | |||
550 | init(); |
||
551 | }); |
||
552 | }; |
||
553 | |||
575 |